// <!--
//  * 严肃声明：
//  * 开源版本请务必保留此注释头信息，若删除我方将保留所有法律责任追究！
//  * 可正常分享和学习源码，不得用于违法犯罪活动，违者必究！
//  * Copyright (c) 2022 APThink David唐 all rights reserved.
//  * 版权所有，侵权必究！
//  *
// -->
/**
 * 通用嵌套树基础类
 * @class
 * @author David Tang<davidtang2018@163.com>
 * 2019-09-23
 */
import { isEmpty, copyObject } from "@/utils"
import { type IOptionNode } from "@/contants"

export class CommonTree {
  _data: Array<any>
  constructor() {
    this._data = []
  }

  add(value: any) {
    const d = this._data.find((x: any) => { return x.uid == value.uid })
    d ? copyObject(value, d) : this._data.push(value)
  }

  delete(uid: string) {
    const i = this._data.findIndex(x => { return x.uid == uid })
    if (i >= 0) {
      this._data.splice(i, 1)
    }
  }

  set data(value: any[]) {
    this._data = value
    this._data.sort((a, b) => {
      if (a.name > b.name) return 1
      else if (a.name == b.name) return 0
      return -1
    })
  }

  get data() {
    return this._data
  }

  //递归生成树状结构数据（添加有叶子的父节点）
  _recursion(data: any, roots: any[]) {
    roots.forEach(r => {
      const childs = this._data.filter(x => { return x.parentuid == r.uid })
      if (childs.length > 0) {
        if (data.children == undefined) {
          data.children = []
        }
        data.children.push({ id: r.uid, label: r.name })
        this._recursion(data.children, childs)
      }
    })
  }

  /**
   * 返回父类树状数据集，不包括叶子节点
   * @return {[type]} [description]
   */
  get parentOptions() {
    const result = new Array<IOptionNode>()
    const roots = this._data.filter(x => { return x.parentuid == undefined || x.parentuid.length == 0})
    roots.forEach(r => {
      //无父节点缺省为一个父节点
      const node = { id: r.uid, value: r.name }
      result.push(node)
      const childs = this._data.filter(x => { return x.parentuid == r.uid })
      if (childs) this._recursion(node, childs)
    })
    return result
  }

  /**
   * 返回顶层树状数据集，没有父类的节点
   * @return {[type]} [description]
   */
  get topOptions() {
    const result = new Array<IOptionNode>()
    const roots = this._data.filter(x => { return x.parentuid == undefined || x.parentuid.length == 0 })
    roots.forEach(r => {
      const node = { id: r.uid, value: r.name }
      result.push(node)
    })
    return result
  }

    //递归生成树状结构数据（所有节点）
    _recursionAll(data: Array<IOptionNode>, roots: any[], excludeMe?: string) {
      let i = 0
      roots.forEach((r) => {
        data.push({ id: r.uid, value: r.name })
        const children = this._data.filter((x) => {
          return x.parentuid == r.uid && x.uid!=excludeMe
        })
        if (children.length > 0) {
          const cs = new Array<IOptionNode>()
          this._recursionAll(cs, children, excludeMe)
          data[i].children = cs
        }
        i++
      })
    }
  
    /**
     * 返回树状数据集，包括叶子节点
     * @return {[type]} [description]
     */
    get nodeOptions() {
      const options = new Array<IOptionNode>()
      const roots = this._data.filter((x) => {
        return x.parentuid == undefined || x.parentuid.length == 0
      })
      this._recursionAll(options, roots)
      return options
    }
  
  
    /**
   * 返回顶层节点
   * @return {[type]} [description]
   */
  get topUids() {
    const result = new Set<string>()
    const roots = this._data.filter(x => { return x.parentuid == undefined || x.parentuid.length == 0 })
    roots.forEach(r => {
      result.add(r.uid)
    })
    return result
  }

  /**
   * 返回有子节点的所有父节点
   */
  get parentUids() {
    const result = new Set<string>()
    this._data.forEach(x => {
      const d = this._data.findIndex(y => {
        return y.parentuid == x.uid
      })
      if (d >= 0) {
        result.add(x.uid)
      }
    })
    return result
  }

  //递归生成所有子节点数据集
  _recursionUid(data: any, nodes: any[]) {
    nodes.forEach(r => {
      data.add(r.uid)
      const childs = this._data.filter(x => { return x.parentuid == r.uid })
      if (childs.length > 0) {
        this._recursionUid(data, childs)
      }
    })
  }

  getChildUids(uid: string) {
    const result = new Set<string>()
    const roots = this._data.filter(x => { return x.uid == uid })
    this._recursionUid(result, roots)
    return result
  }

   /**
	 * 返回指定单位的父单位名称字符串，比如：“总厂-车间”
	 * @param  {[type]} uid [description]
	 * @return {[type]}     [description]
	 */
   getParentName(id: string) {
    const d = this._data.find(s=>{return s.id==id})
    return (d&&d.pid)?this.getParentNameByParentId(d.pid):""
  }

  getParentNameByParentId(pid: string) {
    let str = ""
    let d = this._data.find(s=>{return s.id==pid})
    while (d) {
      str = d.name + "-" + str
      if (d.pid) {
        d = this._data.find(x=>{return x.id==d.pid})
      } else {
        break
      }
    }
    return str?str.substring(0,str.length-1):str
  }

  /**
	 * 返回指定单位的父类
	 * @param  {[type]} value [description]
	 * @return {[type]}     [description]
	 */
  getParent(value: string) {
    if (isEmpty(value)) {
      return undefined
    }
    const result = this._data.find(x=>{return x.uid==value})
    if (result && result.parentuid) {
      return this._data.find(x=>{return x.uid==result.parentuid})
    }
    return undefined
  }

  /**
	 * 返回指定单位的所有父类
	 * @param  {[type]} value [description]
	 * @return {[type]}     [description]
	 */
  getParents(value: string) {
    if (isEmpty(value)) {
      //David: 避免调用者直接使用报错
      return []
    }
    const result = new Set<any>()
    let root = this.getParent(value)
    while (root) {
      result.add(root)
      root = this.getParent(root.parentuid)
    }
    return Array.from(result)
  }

  getNode(uid: string) {
    return this._data.find(x=>{
      return x.uid==uid
    })
  }

  getName(uid: string) {
    const result = this._data.find(x=>{
      return x.uid==uid
    })
    return result?result.name:""
  }

  getNames(uids: string[]) {
    if (isEmpty(uids)) {
      return ""
    }
    const result = new Array<string>()
    uids.forEach(x=>{
      result.push(this.getName(x))
    })
    return result
  }

  getFullName(uid: string) {
    const parentName = this.getParentName(uid)
    const result = this._data.find(x=>{
      return x.uid==uid
    })
    return result?(parentName=="")?result.name:(parentName+"-"+result.name):""
  }
 
}
